package main.java.com.healthy.controller;
import main.java.com.healthy.entity.User;
import main.java.com.healthy.service.ReportService;
import main.java.com.healthy.service.impl.ReportServiceImpl;
import main.java.com.healthy.util.DateUtil;

import java.time.LocalDate;
import java.util.Map;
import java.util.Scanner;

/**
 * 报告生成控制器
 * 对应功能模块：数据统计与报告模块
 */
public class ReportController {
    private ReportService reportService;
    private Scanner scanner;

    public ReportController() {
        this.reportService = new ReportServiceImpl();
        this.scanner = new Scanner(System.in);
    }

    /**
     * 生成报告
     */
    public void generateReports(User user) {
        while (true) {
            System.out.println("\n=== 营养报告 ===");
            System.out.println("1. 生成日报");
            System.out.println("2. 生成周报");
            System.out.println("3. 生成月报");
            System.out.println("4. 营养趋势分析");
            System.out.println("5. 导出报告");
            System.out.println("6. 返回主菜单");
            System.out.print("请选择: ");

            String choice = scanner.nextLine().trim();

            switch (choice) {
                case "1":
                    generateDailyReport(user);
                    break;
                case "2":
                    generateWeeklyReport(user);
                    break;
                case "3":
                    generateMonthlyReport(user);
                    break;
                case "4":
                    analyzeNutritionTrend(user);
                    break;
                case "5":
                    exportReport(user);
                    break;
                case "6":
                    return;
                default:
                    System.out.println("无效选择，请重新输入！");
            }
        }
    }

    /**
     * 生成日报
     */
    private void generateDailyReport(User user) {
        System.out.println("\n=== 日报生成 ===");

        LocalDate reportDate;
        System.out.print("请输入报告日期(YYYY-MM-DD) [今天直接回车]: ");
        String dateInput = scanner.nextLine().trim();
        if (dateInput.isEmpty()) {
            reportDate = LocalDate.now();
        } else {
            try {
                reportDate = LocalDate.parse(dateInput);
            } catch (Exception e) {
                System.out.println("日期格式错误，使用今天日期");
                reportDate = LocalDate.now();
            }
        }

        Map<String, Object> report = reportService.generateDailyReport(user.getUserId(), reportDate);
        displayDailyReport(report, reportDate);

        System.out.println("\n按回车键返回...");
        scanner.nextLine();
    }

    /**
     * 生成周报
     */
    private void generateWeeklyReport(User user) {
        System.out.println("\n=== 周报生成 ===");

        System.out.print("请输入周报开始日期(YYYY-MM-DD): ");
        String startInput = scanner.nextLine().trim();

        LocalDate startDate;
        try {
            startDate = LocalDate.parse(startInput);
        } catch (Exception e) {
            System.out.println("日期格式错误！");
            return;
        }

        Map<String, Object> report = reportService.generateWeeklyReport(user.getUserId(), startDate);
        displayWeeklyReport(report, startDate);

        System.out.println("\n按回车键返回...");
        scanner.nextLine();
    }

    /**
     * 生成月报
     */
    private void generateMonthlyReport(User user) {
        System.out.println("\n=== 月报生成 ===");

        System.out.print("请输入年份: ");
        int year = getValidIntInput(2000, 2100);

        System.out.print("请输入月份(1-12): ");
        int month = getValidIntInput(1, 12);

        Map<String, Object> report = reportService.generateMonthlyReport(user.getUserId(), year, month);
        displayMonthlyReport(report, year, month);

        System.out.println("\n按回车键返回...");
        scanner.nextLine();
    }

    /**
     * 分析营养趋势
     */
    private void analyzeNutritionTrend(User user) {
        System.out.println("\n=== 营养趋势分析 ===");

        System.out.print("请输入开始日期(YYYY-MM-DD): ");
        String startInput = scanner.nextLine().trim();
        System.out.print("请输入结束日期(YYYY-MM-DD): ");
        String endInput = scanner.nextLine().trim();

        LocalDate startDate, endDate;
        try {
            startDate = LocalDate.parse(startInput);
            endDate = LocalDate.parse(endInput);
        } catch (Exception e) {
            System.out.println("日期格式错误！");
            return;
        }

        if (startDate.isAfter(endDate)) {
            System.out.println("开始日期不能晚于结束日期！");
            return;
        }

        Map<String, Double> trend = reportService.getNutritionTrend(user.getUserId(), startDate, endDate);
        displayNutritionTrend(trend, startDate, endDate);

        System.out.println("\n按回车键返回...");
        scanner.nextLine();
    }

    /**
     * 导出报告
     */
    private void exportReport(User user) {
        System.out.println("\n=== 导出报告 ===");

        System.out.print("请输入导出日期(YYYY-MM-DD): ");
        String dateInput = scanner.nextLine().trim();

        LocalDate exportDate;
        try {
            exportDate = LocalDate.parse(dateInput);
        } catch (Exception e) {
            System.out.println("日期格式错误！");
            return;
        }

        System.out.print("请输入导出文件路径: ");
        String filePath = scanner.nextLine().trim();

        if (filePath.isEmpty()) {
            filePath = "report_" + exportDate.toString() + ".txt";
        }

        reportService.exportReportToFile(user.getUserId(), exportDate, filePath);
        System.out.println("报告已导出到: " + filePath);

        System.out.println("\n按回车键返回...");
        scanner.nextLine();
    }

    /**
     * 显示日报
     */
    @SuppressWarnings("unchecked")
    private void displayDailyReport(Map<String, Object> report, LocalDate date) {
        System.out.println("\n==========================================");
        System.out.println("           每日营养报告");
        System.out.println("日期: " + DateUtil.formatDate(date));
        System.out.println("==========================================");

        // 基本信息
        System.out.println("\n=== 基本信息 ===");
        Map<String, Object> basicInfo = (Map<String, Object>) report.get("basicInfo");
        System.out.println("记录天数: " + basicInfo.get("recordDays"));
        System.out.println("总食物种类: " + basicInfo.get("totalFoodTypes"));
        System.out.println("总餐次数: " + basicInfo.get("totalMeals"));

        // 营养摄入
        System.out.println("\n=== 营养摄入 ===");
        Map<String, Double> nutrition = (Map<String, Double>) report.get("nutrition");
        System.out.println("总热量: " + String.format("%.1f", nutrition.get("calories")) + " 千卡");
        System.out.println("总碳水: " + String.format("%.1f", nutrition.get("carbohydrates")) + " g");
        System.out.println("总蛋白质: " + String.format("%.1f", nutrition.get("protein")) + " g");
        System.out.println("总脂肪: " + String.format("%.1f", nutrition.get("fat")) + " g");

        // 餐次分布
        System.out.println("\n=== 餐次分布 ===");
        Map<String, Double> mealDistribution = (Map<String, Double>) report.get("mealDistribution");
        for (Map.Entry<String, Double> entry : mealDistribution.entrySet()) {
            System.out.println(entry.getKey() + ": " + String.format("%.1f", entry.getValue()) + " 千卡");
        }

        // 食物类别分布
        System.out.println("\n=== 食物类别分布 ===");
        Map<String, Double> categoryDistribution = (Map<String, Double>) report.get("categoryDistribution");
        for (Map.Entry<String, Double> entry : categoryDistribution.entrySet()) {
            double percentage = (entry.getValue() / nutrition.get("calories")) * 100;
            System.out.println(entry.getKey() + ": " + String.format("%.1f", entry.getValue()) +
                    " 千卡 (" + String.format("%.1f", percentage) + "%)");
        }

        // 评估结果
        System.out.println("\n=== 营养评估 ===");
        Map<String, String> assessment = (Map<String, String>) report.get("assessment");
        for (Map.Entry<String, String> entry : assessment.entrySet()) {
            System.out.println(entry.getKey() + ": " + entry.getValue());
        }

        System.out.println("==========================================");
    }

    /**
     * 显示周报
     */
    @SuppressWarnings("unchecked")
    private void displayWeeklyReport(Map<String, Object> report, LocalDate startDate) {
        LocalDate endDate = startDate.plusDays(6);

        System.out.println("\n==========================================");
        System.out.println("           每周营养报告");
        System.out.println("周期: " + DateUtil.formatDate(startDate) + " - " + DateUtil.formatDate(endDate));
        System.out.println("==========================================");

        // 基本信息
        System.out.println("\n=== 基本信息 ===");
        Map<String, Object> basicInfo = (Map<String, Object>) report.get("basicInfo");
        System.out.println("记录天数: " + basicInfo.get("recordDays") + "/7");
        System.out.println("平均每日食物种类: " + String.format("%.1f", basicInfo.get("avgFoodTypes")));
        System.out.println("平均每日餐次数: " + String.format("%.1f", basicInfo.get("avgMeals")));

        // 营养摄入
        System.out.println("\n=== 营养摄入 ===");
        Map<String, Double> nutrition = (Map<String, Double>) report.get("nutrition");
        System.out.println("周总热量: " + String.format("%.0f", nutrition.get("totalCalories")) + " 千卡");
        System.out.println("平均每日热量: " + String.format("%.0f", nutrition.get("averageCalories")) + " 千卡");
        System.out.println("平均每日碳水: " + String.format("%.1f", nutrition.get("averageCarbs")) + " g");
        System.out.println("平均每日蛋白质: " + String.format("%.1f", nutrition.get("averageProtein")) + " g");
        System.out.println("平均每日脂肪: " + String.format("%.1f", nutrition.get("averageFat")) + " g");

        // 每日趋势
        System.out.println("\n=== 每日热量趋势 ===");
        Map<String, Double> dailyCalories = (Map<String, Double>) report.get("dailyCalories");
        for (Map.Entry<String, Double> entry : dailyCalories.entrySet()) {
            System.out.println(entry.getKey() + ": " + String.format("%.0f", entry.getValue()) + " 千卡");
        }

        // 评估结果
        System.out.println("\n=== 周度评估 ===");
        Map<String, String> assessment = (Map<String, String>) report.get("assessment");
        for (Map.Entry<String, String> entry : assessment.entrySet()) {
            System.out.println(entry.getKey() + ": " + entry.getValue());
        }

        System.out.println("==========================================");
    }

    /**
     * 显示月报
     */
    @SuppressWarnings("unchecked")
    private void displayMonthlyReport(Map<String, Object> report, int year, int month) {
        System.out.println("\n==========================================");
        System.out.println("           每月营养报告");
        System.out.println("月份: " + year + "年" + month + "月");
        System.out.println("==========================================");

        // 基本信息
        System.out.println("\n=== 基本信息 ===");
        Map<String, Object> basicInfo = (Map<String, Object>) report.get("basicInfo");
        System.out.println("记录天数: " + basicInfo.get("recordDays"));
        System.out.println("记录率: " + String.format("%.1f", basicInfo.get("recordRate")) + "%");
        System.out.println("平均每日食物种类: " + String.format("%.1f", basicInfo.get("avgFoodTypes")));

        // 营养摄入
        System.out.println("\n=== 营养摄入 ===");
        Map<String, Double> nutrition = (Map<String, Double>) report.get("nutrition");
        System.out.println("月总热量: " + String.format("%.0f", nutrition.get("totalCalories")) + " 千卡");
        System.out.println("平均每日热量: " + String.format("%.0f", nutrition.get("averageCalories")) + " 千卡");
        System.out.println("热量标准差: " + String.format("%.0f", nutrition.get("calorieStd")) + " 千卡");

        // 每周趋势
        System.out.println("\n=== 每周热量趋势 ===");
        Map<String, Double> weeklyCalories = (Map<String, Double>) report.get("weeklyCalories");
        for (Map.Entry<String, Double> entry : weeklyCalories.entrySet()) {
            System.out.println(entry.getKey() + ": " + String.format("%.0f", entry.getValue()) + " 千卡/天");
        }

        // 食物类别分析
        System.out.println("\n=== 食物类别分析 ===");
        Map<String, Double> categoryAnalysis = (Map<String, Double>) report.get("categoryAnalysis");
        for (Map.Entry<String, Double> entry : categoryAnalysis.entrySet()) {
            System.out.println(entry.getKey() + ": " + String.format("%.1f", entry.getValue()) + "%");
        }

        // 月度总结
        System.out.println("\n=== 月度总结 ===");
        Map<String, String> summary = (Map<String, String>) report.get("summary");
        for (Map.Entry<String, String> entry : summary.entrySet()) {
            System.out.println(entry.getKey() + ": " + entry.getValue());
        }

        System.out.println("==========================================");
    }

    /**
     * 显示营养趋势
     */
    private void displayNutritionTrend(Map<String, Double> trend, LocalDate startDate, LocalDate endDate) {
        System.out.println("\n==========================================");
        System.out.println("           营养趋势分析");
        System.out.println("周期: " + DateUtil.formatDate(startDate) + " - " + DateUtil.formatDate(endDate));
        System.out.println("==========================================");

        System.out.println("\n=== 趋势分析 ===");
        System.out.println("平均每日热量: " + String.format("%.0f", trend.get("avgCalories")) + " 千卡");
        System.out.println("热量变化趋势: " + getTrendDescription(trend.get("calorieTrend")));
        System.out.println("平均每日碳水: " + String.format("%.1f", trend.get("avgCarbs")) + " g");
        System.out.println("平均每日蛋白质: " + String.format("%.1f", trend.get("avgProtein")) + " g");
        System.out.println("平均每日脂肪: " + String.format("%.1f", trend.get("avgFat")) + " g");

        System.out.println("\n=== 稳定性分析 ===");
        double stability = trend.get("stability");
        System.out.println("摄入稳定性: " + String.format("%.1f", stability * 100) + "%");
        if (stability > 0.8) {
            System.out.println("评价: 摄入非常稳定");
        } else if (stability > 0.6) {
            System.out.println("评价: 摄入较为稳定");
        } else {
            System.out.println("评价: 摄入波动较大");
        }
    }

    /**
     * 获取趋势描述
     */
    private String getTrendDescription(double trend) {
        if (trend > 0.1) {
            return "上升趋势";
        } else if (trend < -0.1) {
            return "下降趋势";
        } else {
            return "平稳趋势";
        }
    }

    // 辅助方法
    private int getValidIntInput(int min, int max) {
        while (true) {
            try {
                String input = scanner.nextLine().trim();
                int value = Integer.parseInt(input);
                if (value >= min && value <= max) {
                    return value;
                } else {
                    System.out.print("输入值应在 " + min + " 到 " + max + " 之间，请重新输入: ");
                }
            } catch (NumberFormatException e) {
                System.out.print("请输入有效的整数: ");
            }
        }
    }
}